package org.infodavid.common.ejb;

import java.util.HashMap;
import java.util.Map;

import javax.ejb.Local;
import javax.ejb.PrePassivate;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;

import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.annotations.Persister;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;

import org.infodavid.common.ejb.components.SecuredObjectIdentifierComponent;
import org.infodavid.common.impl.model.security.AccessControlEntryImpl;
import org.infodavid.common.model.impl.persisters.VersionSafeSingleTableEntityPersister;
import org.infodavid.common.model.security.IAccessControlEntry;
import org.infodavid.common.model.security.IAccessControlList;
import org.infodavid.common.model.security.ISecuredObjectIdentifier;
import org.infodavid.common.persistence.INamed;

/**
 * The Class AccessControlEntryBean.
 */
@Entity(name = "IAccessControlEntry")
@org.hibernate.annotations.Entity(dynamicUpdate = true, selectBeforeUpdate = true, dynamicInsert = true, optimisticLock = OptimisticLockType.VERSION)
@Persister(impl = VersionSafeSingleTableEntityPersister.class)
@Table(name = "ACES")
@Local(value = IAccessControlEntry.class)
public class AccessControlEntryBean extends AccessControlEntryImpl {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1660345027625851667L;

	/** The acl. */
	private IAccessControlList acl;

	/**
	 * The Constructor.
	 * @throws Exception the exception
	 */
	protected AccessControlEntryBean() throws Exception {
		super();
	}

	/**
	 * The Constructor.
	 * @param keyArg the key arg
	 * @throws Exception the exception
	 */
	protected AccessControlEntryBean(final Long keyArg) throws Exception {
		super(keyArg);
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.security.AccessControlListImpl#init()
	 */
	@Override
	@PrePassivate
	public void init() throws Exception {
		super.init();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#getCreationDate()
	 */
	@Override
	@Column(name = CREATION_DATE, nullable = false, updatable = false)
	@Type(type = "org.infodavid.persistence.impl.hibernate.usertype.DateTimeUserType")
	@Index(name = "IDX_ACES_CREATIONDATE")
	public DateTime getCreationDate() {
		return super.getCreationDate();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#getModificationDate()
	 */
	@Override
	@Version
	@Column(name = MODIFICATION_DATE, nullable = false)
	@Type(type = "org.infodavid.persistence.impl.hibernate.usertype.DateTimeUserType")
	public DateTime getModificationDate() {
		return super.getModificationDate();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#getKey()
	 */
	@Override
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = ID, nullable = false)
	public Long getKey() {
		return super.getKey();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#isArchived()
	 */
	@Override
	@Column(name = ARCHIVED, nullable = false)
	@Index(name = "IDX_ACES_ARCHIVED")
	public boolean isArchived() {
		return super.isArchived();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.security.AccessControlEntryImpl#getObjectIdentifier()
	 */
	@Override
	@Embedded
	@Target(value = SecuredObjectIdentifierComponent.class)
	public ISecuredObjectIdentifier getObjectIdentifier() {
		return super.getObjectIdentifier();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.security.AccessControlEntryImpl#getPermissions()
	 */
	@Override
	@ElementCollection(fetch = FetchType.LAZY)
	@CollectionTable(name = "ACES_PERMISSIONS", joinColumns = @JoinColumn(name = ID, nullable = false), uniqueConstraints = @UniqueConstraint(name = "UC_ACES_PERMISSIONS", columnNames = {
	    INamed.NAME, ID
	}))
	@MapKeyColumn(name = INamed.NAME, length = 32, nullable = false)
	@Column(name = "value", length = 512, nullable = true)
	@ForeignKey(name = "FK_ACES_PERMISSIONS")
	@Target(value = HashMap.class)
	public Map<String,Boolean> getPermissions() {
		return super.getPermissions();
	}

	/**
	 * Gets the ACL.
	 * @return the ACL
	 */
	@JoinColumn(name = IAccessControlList.ID, referencedColumnName = IAccessControlList.ID, nullable = true, updatable = false)
	@ManyToOne(optional = true, targetEntity = AccessControlListBean.class, fetch = FetchType.LAZY)
	@ForeignKey(name = "FK_ACES_ACL")
	public IAccessControlList getAcl() {
		return acl;
	}

	/**
	 * Sets the acl.
	 * @param value the new acl
	 */
	public void setAcl(final IAccessControlList value) {
		acl = value;
	}
}
